{% extends 'core/Broken Access Control/broken-access.html' %} {% load static %} Title {% block inside-content %}

But how do we prevent this?

Preventing this issue is easier than it may seem. For Broken Access prevention, we will use authentication. What I recommend the most is using libraries. Many big frameworks have built-in libraries that take care of it for us. This website uses UserCreationForm, AuthenticationForm for Django.
Other examples may include PHP OAuth 2.0 Server for PHP, Microsoft Authentication Library (MSAL) for .NET , and many others.

Now let's look at some examples

First, let's see what we are even doing. You can see this as an anonymous user without any authorization.

First, create an account on the Sign up page you can use for testing, for example:


As you can see, once we logged in, a new tab appeared. This is an example of prevention against Broken Access Control. You can also try to log out and access the following:

http://127.0.0.1:8000/profile

After accessing the URL without authentication, users will be automatically rerouted to the main page. Now let us look at how to implement it.

1. Preparations

To display our content only to selected people, we first need a way to distinguish logged-in users from anonymous browsers. For that, we implement a log-in/register system. We start that off by making a simple database. Some frameworks like Django will generate their structure, lessening your workload. But let's assume you need to do it yourself.

As you can see, this is an exemplary structure you could use for your project, obviously adding or removing tables based on your needs. Take a note of some important columns like - is_superuser. This is, again, Django's way of checking admin authentication—however, a good practice in any other project. If you require more permission levels, you could add a column with the same name and instead use Integers. Now that we can see if a user can access certain pages or not, let's use it.

First, we need a code to check whether users accessing specific URLs are authenticated. This will be explained in general terms, as it would be a whole other topic if we were to code the entire implementation. To authenticate our users, we will allow them to register. Registration and login are usually done through forms.
Example:

<form method="post">
    { csrf_token }
    {% for field in form %}
        <p>
        {{ field.label_tag }}
        {{ field }}
        {% for error in field.errors %;}
          <p style="color: red">{{ error }}</p>
        {% endfor %}
      </p>
    {% endfor %}
     <button type="submit" class="btn btn-success">Sign up</button>
  </form>

Here you can see an example of registration forms. We loop through fields in the forms. Forms contain three fields, username, password, and password confirmation. Similarly, we loop through errors if the sign-up fails. field.label_tag displays name of each field. You can see how these variables are bound to our views file in the step below.

2. Working with data

The form displays the predefined username, password, and password confirmation fields in this example. Same would be used for user login. Now we have a way to get input from our user; we need a backend logic that will make queries to our database to see if this user already exists.
Example of a query:

SELECT * FROM testDatabase.auth_user WHERE username="user1";

Queries like these allow us to check if the user already exists. If it does, we can authorize and log him in. However, our queries look a bit different. You can check that in the Injections tutorial.

def signup(request):
    if request.user.is_authenticated:
        return redirect('/')
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password1')
            user = authenticate(username=username, password=password)
            login(request, user)
            return redirect('/')
        else:
            return render(request, 'core/signup.html', {'form': form})
    else:
        form = UserCreationForm()
        return render(request, 'core/signup.html', {'form': form})

Since we want only one type of request on our sign-up page, we first check if the incoming communication is POST. If so, we read the username and password fields and create a form. The "UserCreationForm" function checks if the credentials are correct, such as if the username doesn't exist or if the password follows all necessary validators. If credentials pass all the checks, we create the form. If not, we return the form containing the error message. A valid form will be saved into the website's database. After that, we take the username and password from the valid form, authenticate and log the user in. This process is similar to log-in except for creating the form.
Now that we have verified our user, we need to foolproof where he can get access. The image at the top being used as an example.

3. Access proofing our app

In this last step, we will condition all the views/URLs we want to separate from non-logged-in users. Since we now know when users are logged in, we can easily separate them. Such as:


{% if user.is_authenticated %}
<li>
    <a href="/profile"
</li>
{% endif %}
            

This is a simple front-end check with an "if" condition that only displays the profile tab to authenticated users. However, if we were only to condition it on the front end, it could still be accessed through URL change /profile. So let's see how to prevent that.


def profile(request):
    if request.user.is_authenticated:
        return render(request, 'core/Profile.html')
    else:
        return redirect('/')
            

In the views, we define a simple method to get called each time somebody clicks our /profile link. The check is the same as in the front end, but we return our profile view here. If the user's authentication fails, he gets rerouted to the homepage.

{% endblock %}